"""unittest compatibility layer"""

from sys import version_info as __python_version  # Must first import
if __python_version[:2] >= (2, 7):                # pprint if it needs
    import adm._compatibility._pprint as pprint   # to be patched.


import unittest  # Imported into its own namespace for monkey patching.


try:
    unittest.TestCase.assertIs  # New in 3.1
    unittest.TestCase.assertIsNot
    unittest.TestCase.assertIsNone
    unittest.TestCase.assertIsNotNone
    unittest.TestCase.assertIn
    unittest.TestCase.assertNotIn
except AttributeError:
    class TestCase(unittest.TestCase):
        # The following methods were adapted from code in the
        # Python 3.1 standard library (unittest.py).
        def assertIs(self, expr1, expr2, msg=None):
            """Just like self.assertTrue(a is b), but with a nicer default message."""
            if expr1 is not expr2:
                standardMsg = '%r is not %r' % (expr1, expr2)
                self.fail(self._formatMessage(msg, standardMsg))

        def assertIsNot(self, expr1, expr2, msg=None):
            """Just like self.assertTrue(a is not b), but with a nicer default message."""
            if expr1 is expr2:
                standardMsg = 'unexpectedly identical: %r' % (expr1,)
                self.fail(self._formatMessage(msg, standardMsg))

        def assertIsNone(self, obj, msg=None):
            """Same as self.assertTrue(obj is None), with a nicer default message."""
            if obj is not None:
                standardMsg = '%r is not None' % obj
                self.fail(self._formatMessage(msg, standardMsg))

        def assertIsNotNone(self, obj, msg=None):
            """Included for symmetry with assertIsNone."""
            if obj is None:
                standardMsg = 'unexpectedly None'
                self.fail(self._formatMessage(msg, standardMsg))

        def assertIn(self, member, container, msg=None):
            """Just like self.assertTrue(a in b), but with a nicer default message."""
            if member not in container:
                standardMsg = '%r not found in %r' % (member, container)
                self.fail(self._formatMessage(msg, standardMsg))

        def assertNotIn(self, member, container, msg=None):
            """Just like self.assertTrue(a not in b), but with a nicer default message."""
            if member in container:
                standardMsg = '%r unexpectedly found in %r' % (member, container)
                self.fail(self._formatMessage(msg, standardMsg))

    unittest.TestCase = TestCase  # Monkey patch.


try:
    unittest.TestCase.assertIsInstance  # New in 3.2
    unittest.TestCase.assertNotIsInstance
except AttributeError:
    class TestCase(unittest.TestCase):
        # The following methods were adapted from code in the
        # Python 3.2 standard library (unittest/case.py).
        def assertIsInstance(self, obj, cls, msg=None):
            """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
            default message."""
            if not isinstance(obj, cls):
                standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
                self.fail(self._formatMessage(msg, standardMsg))

        def assertNotIsInstance(self, obj, cls, msg=None):
            """Included for symmetry with assertIsInstance."""
            if isinstance(obj, cls):
                standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
                self.fail(self._formatMessage(msg, standardMsg))

    unittest.TestCase = TestCase  # Monkey patch.


try:
    unittest.TestCase.assertRaisesRegex  # Renamed in 3.2 (previously assertRaisesRegexp)
except AttributeError:
    try:
        unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp  # New in 2.7
    except AttributeError:
        import re
        class TestCase(unittest.TestCase):
            # The following method was adapted from unittest2 source
            # code <http://pypi.python.org/pypi/unittest2>.
            # Copyright 2010 Michael Foord, released under the BSD License.
            def assertRaisesRegex(self, expected_exception, expected_regexp,
                                   callable_obj=None, *args, **kwargs):
                """Asserts that the message in a raised exception matches a regexp.

                Args:
                    expected_exception: Exception class expected to be raised.
                    expected_regexp: Regexp (re pattern object or string) expected
                            to be found in error message.
                    callable_obj: Function to be called.
                    args: Extra args.
                    kwargs: Extra kwargs.
                """
                if callable_obj is None:
                    return unittest._AssertRaisesContext(expected_exception, self, expected_regexp)
                try:
                    callable_obj(*args, **kwargs)
                except expected_exception as exc_value:
                    #if isinstance(expected_regexp, basestring):
                    if isinstance(expected_regexp, str):
                        expected_regexp = re.compile(expected_regexp)
                    if not expected_regexp.search(str(exc_value)):
                        raise self.failureException('"%s" does not match "%s"' %
                                 (expected_regexp.pattern, str(exc_value)))
                else:
                    if hasattr(expected_exception, '__name__'):
                        excName = expected_exception.__name__
                    else:
                        excName = str(expected_exception)
                    raise self.failureException("%s not raised" % excName)

        unittest.TestCase = TestCase  # Monkey patch.


from unittest import *  # Pull into local namespace now that we're finished monkey patching.


try:
    skip  # New in 3.1
    SkipTest
except NameError:
    import adm._compatibility._functools as functools
    # The following function and class were adapted from code in the
    # Python 3.1 standard library (unittest.py).
    def skip(reason):
        """
        Unconditionally skip a test.
        """
        def decorator(test_item):
            if isinstance(test_item, type) and issubclass(test_item, TestCase):
                test_item.__unittest_skip__ = True
                test_item.__unittest_skip_why__ = reason
                return test_item
            @functools.wraps(test_item)
            def skip_wrapper(*args, **kwargs):
                raise SkipTest(reason)
            return skip_wrapper
        return decorator

    class SkipTest(Exception):
        """
        Raise this exception in a test to skip it.

        Usually you can use TestResult.skip() or one of the skipping decorators
        instead of raising this directly.
        """
        pass
